﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using RestSharp;
using System.Threading.Tasks;
using System.Net;

namespace RATSharp.Rest
{
    static class RestResponseTaskFactory
    {
        public static Task<T> ExecuteTaskAsync<T>(this RestClient @this, RestRequest request, RestService service)
    where T : new()
        {
          
            if (@this == null || service == null || request == null)
                throw new NullReferenceException();
            var tcs = new TaskCompletionSource<T>();
            if (service.sessionCookie != null)
            {
                request.AddParameter(service.sessionCookie.Name, service.sessionCookie.Value, ParameterType.Cookie);
            }

            @this.ExecuteAsync<T>(request, (response) =>
             {
                 if (response.StatusCode == System.Net.HttpStatusCode.Unauthorized)
                 {
                     extractCookie<T>(service, response);
                     @this.Authenticator = new HttpBasicAuthenticator(service.properties.username, service.properties.password);
                     //Try to send data again with manager

                     @this.ExecuteAsync<T>(request, (authResponse) =>
                     {
                         try
                         {
                             if (authResponse.ErrorException != null)
                             {
                                 tcs.TrySetException(authResponse.ErrorException);
                             }
                             else
                             {
                                 extractCookie<T>(service, authResponse);
                                 tcs.TrySetResult(authResponse.Data);
                             }
                         }
                         finally
                         {
                             @this.Authenticator = null;
                         }
                     });

                 }
                 else
                 {
                     if (response.ErrorException != null)
                     {
                         tcs.TrySetException(response.ErrorException);
                     }
                     else
                     {
                         extractCookie<T>(service, response);
                         tcs.TrySetResult(response.Data);
                     }
                 }
             });

            return tcs.Task;

        }

        private static void extractCookie<T>(RestService service, IRestResponse<T> response)
        {
            //Restsharp cannot recognize our JSESSIONID cookies so we must do that manually from
            //HTTP headers - also if your cookies are missing, please check (e.g. with CURL) if cookies 
            //contains "Domain" part - because WP7 does not support cookies without DOMAIN
            foreach (Parameter param in response.Headers)
            {
                if (param.Name.Equals("Set-Cookie") && param.Value.ToString().StartsWith(RestService.SESSION_COOKIE_KEY)) 
                {
                    string sourceString = param.Value.ToString();
                    string removeString = RestService.SESSION_COOKIE_KEY + "=";
                    int index = sourceString.IndexOf(removeString);
                    string cleanPath = (index < 0) ? sourceString : sourceString.Remove(index, removeString.Length);
                    cleanPath = cleanPath.Split(';')[0];
                    Parameter newParam = new Parameter();
                    newParam.Name = RestService.SESSION_COOKIE_KEY;
                    newParam.Type = ParameterType.Cookie;
                    newParam.Value = cleanPath;
                    service.sessionCookie = newParam;
                }
            }
        }
    }
}
